/*
 * Copyright (c) 2020 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * introduction:
 * Mrobot UnionDevices V2 版本  
 * 简易门锁 door_mqtt.c 支持云端、机器人双通道控制
 * 每台互联设备 对应fan_mqtt.c door_mqtt.c  lamb_mqtt.c  water_mqtt.c 编译记得修改 BUILD.gn
 * data:2022.05.30 HelloKun 优化
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"

#include "wifi_connect.h"
#include "MQTTClient.h"

#include "wifiiot_errno.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_adc.h"
#include "wifiiot_uart.h"
#include "wifiiot_pwm.h"
#include "hi_uart.h"
#include "hi_time.h" // hi_udelay()

#define UART_BUFF_SIZE 1000
#define MQTT_BUFF_SIZE 1000
#define DOOR_TASK_STARCK 10240
#define UART_TIMEOUT 10
#define MQTT_CMD_TIME 2000
#define MQTT_QOS2 2
#define TASK_TIME 200
#define COUNT_MAX 1000

#define DOOR_PWM800 800
#define DOOR_PWM1500 1500
#define PWM_FULL 20000
#define SERVO_SLEEP 1

#define MQTT_PORT 1883
#define MQTT_IP "192.168.1.1"
#define WIFI_NAME "r1"
#define WIFI_SWD "88888889"
#define WAIT_MSG '5'

typedef enum
{
	DOOR_OPEN_1 = 49, // '1'
	DOOR_DEVICE_2,	  // '2'
} door_status;

static const char *data = "MRobot_door\r\n";
uint8_t uart_buff[UART_BUFF_SIZE] = {0};
uint8_t *uart_buff_ptr = uart_buff;
char mqtt_buff[MQTT_BUFF_SIZE] = {0};

static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];

Network network;

void messageArrived(MessageData *data)
{
	printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data,
		   data->message->payloadlen, data->message->payload);
	strcpy(mqtt_buff, data->message->payload);
	printf("mqtt_buff%s \n", mqtt_buff);
}

static void MyUartInit(void)
{
	uint32_t ret;
	WifiIotUartAttribute uart_attr = {
		.baudRate = 115200,
		.dataBits = 8,
		.stopBits = 1,
		.parity = 0,
	};

	// Initialize uart driver
	ret = UartInit(WIFI_IOT_UART_IDX_1, &uart_attr, NULL);
	if (ret != WIFI_IOT_SUCCESS)
	{
		printf("Failed to init uart! Err code = %d\n", ret);
		return;
	}
}

static void DoorInit(void)
{
	GpioInit();
	IoSetFunc(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_IO_FUNC_GPIO_10_GPIO);
	GpioSetDir(WIFI_IOT_GPIO_IDX_10, WIFI_IOT_GPIO_DIR_OUT);
}
/* @brief  Servo  control *
 @param angle  input value: 500-2500 *
*/
void My_servo(int angle)
{
	int j = 0;
	for (j = 0; j < 10; j++)
	{
		GpioInit();
		GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, WIFI_IOT_GPIO_VALUE1);
		hi_udelay(angle); // angle ms
		GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, WIFI_IOT_GPIO_VALUE0);
		hi_udelay(PWM_FULL - angle);
	} // 20ms 控制舵机
}

static void DoorCtr(void)
{
	hi_uart_read_timeout(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE, UART_TIMEOUT);
	printf("Uart1 read door data:%s \n", uart_buff_ptr);
	if ((uart_buff[0] == DOOR_DEVICE_2) && (uart_buff[1] == DOOR_OPEN_1))
	{
		// 模拟20ms周期 PWM  控制舵机开门
		printf("******* Open Door *****\n");
		My_servo(DOOR_PWM800); // 开门
		sleep(SERVO_SLEEP);
		My_servo(DOOR_PWM1500);
		uart_buff[0] = WAIT_MSG;
	}

	if ((mqtt_buff[0] == DOOR_DEVICE_2) && (mqtt_buff[1] == DOOR_OPEN_1))
	{
		// 模拟20ms周期 PWM  控制舵机开门
		printf("******* Open Door *****\n");
		My_servo(DOOR_PWM800);
		sleep(SERVO_SLEEP);
		My_servo(DOOR_PWM1500);
		mqtt_buff[0] = WAIT_MSG;
	}
	printf("******* Auto Reset Door *****\n");
}

static void MQTT_DoorTask(void)
{
	WifiConnect(WIFI_NAME, WIFI_SWD);
	printf("Starting ...\n");
	int rc, count = 0;
	MQTTClient client;

	NetworkInit(&network);
	printf("NetworkConnect  ...\n");

	MyUartInit();
	DoorInit();
	My_servo(DOOR_PWM1500);
begin:
	NetworkConnect(&network, MQTT_IP, MQTT_PORT); // mqtt iot server
	printf("MQTTClientInit  ...\n");
	MQTTClientInit(&client, &network, MQTT_CMD_TIME, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

	MQTTString clientId = MQTTString_initializer;
	clientId.cstring = "MRobot_door";

	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
	data.clientID = clientId;
	data.willFlag = 0;
	data.MQTTVersion = 3;
	data.keepAliveInterval = 0;
	data.cleansession = 1;

	printf("MQTTConnect  ...\n");
	rc = MQTTConnect(&client, &data);
	if (rc != 0)
	{
		printf("MQTTConnect: %d\n", rc);
		NetworkDisconnect(&network);
		MQTTDisconnect(&client);
		osDelay(TASK_TIME);
		goto begin;
	}

	printf("MQTTSubscribe  ...\n");
	// 其他设备 web_fan_btn web_lamb_btn  web_water_btn
	rc = MQTTSubscribe(&client, "web_door_btn", MQTT_QOS2, messageArrived); // 回调
	if (rc != 0)
	{
		printf("MQTTSubscribe: %d\n", rc);
		osDelay(TASK_TIME);
		goto begin;
	}

	while (++count)
	{
		DoorCtr(); // 串口、mqtt数据控制门

		MQTTMessage message;
		char payload[30];

		message.qos = MQTT_QOS2;
		message.retained = 0;
		message.payload = payload;
		sprintf(payload, "message number %d", count);
		message.payloadlen = strlen(payload);

		// 其他设备 发布fan lamb water
		if ((rc = MQTTPublish(&client, "door", &message)) != 0)
		{
			printf("Return code from MQTT publish is %d\n", rc);
			NetworkDisconnect(&network);
			MQTTDisconnect(&client);
			goto begin;
		}
		osDelay(TASK_TIME);
		if (count > COUNT_MAX)
		{
			count = 1;
		}
		printf("----- count = %d ------\r\n", count);
	}
}
static void MQTT_Door(void)
{
	osThreadAttr_t attr;

	attr.name = "MQTT_DoorTask";
	attr.attr_bits = 0U;
	attr.cb_mem = NULL;
	attr.cb_size = 0U;
	attr.stack_mem = NULL;
	attr.stack_size = DOOR_TASK_STARCK;
	attr.priority = osPriorityNormal;

	if (osThreadNew((osThreadFunc_t)MQTT_DoorTask, NULL, &attr) == NULL)
	{
		printf("[MQTT_Door] Falied to create MQTT_DoorTask!\n");
	}
}
APP_FEATURE_INIT(MQTT_Door);
